home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gekkan Dennou Club 147
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z
/
Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin
/
games
/
greversi
/
grevvs.lzh
/
src
/
think.s
< prev
next >
Wrap
Text File
|
2000-02-04
|
53KB
|
2,181 lines
;----------------------------------------------------------------
; greversi.x v0.14 (2000.02.04) by M.Kamada
; think.s 盤操作・思考ルーチン
;----------------------------------------------------------------
.include doscall.mac
.include const.equ
;----------------------------------------------------------------
;α-β法
;
; 相手の番(min) →β=1
;
; 自分の番(max) α=1 α>=3>=β→βカット
;
; 自分の評価値 -3 1 -7 3 (-1 2)
;----------------------------------------------------------------
;石差を計算する
;<d6.b:自分の石
;<d7.b:相手の石
;>d0.w:石差(自分の石の数-相手の石の数)
;>z-flag:eq=引き分け
;>n-flag:mi=自分が相手に負けている
.text
.align 4,$2048
get_sekisa::
movem.l d1-d2/a0,-(sp)
moveq.l #0,d0
lea.l ban+P11,a0
moveq.l #P88-P11,d1
1: move.b (a0)+,d2
ble 3f
cmp.b d6,d2
bne 2f
addq.w #1,d0
dbra d1,1b
bra 4f
2: subq.w #1,d0
3: dbra d1,1b
4: tst.w d0
movem.l (sp)+,d1-d2/a0
rts
;----------------------------------------------------------------
;盤を初期化する
.text
.align 4,$2048
init_think::
movem.l a0-a1,-(sp)
lea.l ban,a0
lea.l sban,a1
.rept (BAN_LEN+3)/4
move.l (a1)+,(a0)+
.endm
movem.l (sp)+,a0-a1
rts
;----------------------------------------------------------------
;思考ルーチン
; 自分の石を置ける位置が1箇所以上あるときだけ呼び出すこと
;<d0.w:レベル(1~5)
;<d6.b:自分の石
;<d7.b:相手の石
;>d0.l:置く位置(盤の先頭からのオフセット)
.text
.align 4,$2048
think::
movem.l d1-d7/a0-a6,-(sp)
;レベル設定
lea.l (level_table,pc),a0
subq.w #1,d0
lsl.w #3,d0
adda.w d0,a0
move.w (a0)+,depth_level
move.w (a0)+,hisshou_level
move.w (a0)+,kanzen_level
;空いているマスを数える
moveq.l #0,d0
lea.l ban+P11,a0
moveq.l #P88-P11,d1
1: tst.b (a0)+
bne @f
addq.w #1,d0
@@: dbra d1,1b
move.w d0,aki_count
;終盤の読み切り
bsr yomikiri
bne 99f
;定石探索
bsr joseki
bne 99f ;定石による手が見つかった
;自分が置ける場所のリストを作る
bsr list_ban
lea.l eval_list,a2 ;リストの先頭(評価値が大きい順に並べる)
movea.l a2,a3
clr.l (a3)+ ;置く位置(番兵なので0)
clr.l (a3)+ ;次のセルへのポインタ(番兵なので無効)
move.l #$80000000,(a3)+ ;評価値(番兵なので最小値)
move.l (a1)+,d0 ;置く位置
1: movea.l d0,a0 ;置く位置
move.l a0,(a3) ;置く位置
bsr put_record_one
exg.l d6,d7
bsr eval ;評価してみる
exg.l d6,d7
neg.l d0
move.l d0,(8,a3) ;評価値
movea.l a2,a0 ;リストの先頭
bra 16f
15: movea.l a0,a4 ;直前のセルへのポインタ
movea.l (4,a0),a0
16: cmp.l (8,a0),d0 ;評価値を比較
ble 15b
move.l a0,(4,a3) ;次のセルへのポインタ
cmpa.l a2,a0
beq 17f
move.l a3,(4,a4) ;直前のセルの次のセルへのポインタを更新する
bra 18f
17: movea.l a3,a2 ;リストの先頭を更新する
18: lea.l (12,a3),a3 ;次の空きセル
bsr tup_record_one
move.l (a1)+,d0 ;置く位置
bne 1b
;ミニマックス法+α-β法
moveq.l #0,d3 ;最大の評価値を得た手の数
move.w depth_level,d4
subq.w #1,d4 ;先読みの深さ
movea.l #$80000000,a3 ;α
movea.l #$7FFFFFFF,a4 ;β
movea.l a2,a1 ;置く位置のリストの先頭
move.l (a1)+,d0 ;置く位置
1: movea.l d0,a0 ;置く位置
bsr put_record_one
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr eval_min ;相手の手番で自分の評価値の最小値を求める
exg.l d6,d7
cmp.l a3,d0
blt 2f
bgt 3f
;最大の評価値が同一
addq.w #1,d3 ;最大の評価値を得た手の数
bsr myrand
and.l #$0000FFFF,d0
divu.w d3,d0
swap.w d0
tst.w d0
beq 4f ;n番目の手は1/nの確率で採用される
bra 2f
3: moveq.l #1,d3 ;最大の評価値を得た手の数
movea.l d0,a3 ;αを更新
4: movea.l a0,a2 ;相手の手番で自分の評価値の最小値が最大になる手
2: bsr tup_record_one
movea.l (a1)+,a1 ;次のセルへのポインタ(最後に番兵が出てくる)
move.l (a1)+,d0 ;置く位置(番兵のセルは0)
bne 1b
move.l a2,d0 ;相手の手番で自分の評価値の最小値が最大になる手
sub.l #ban,d0
99: movem.l (sp)+,d1-d7/a0-a6
rts
level_table: .dc.w 2,8,6,0
.dc.w 3,10,8,0
.dc.w 4,12,10,0
.dc.w 5,14,12,0
.dc.w 6,16,14,0
.bss
.even
depth_level: .ds.w 1
hisshou_level: .ds.w 1
kanzen_level: .ds.w 1
aki_count: .ds.w 1
.align 4
eval_list: .ds.l 3*(60+1)
;----------------------------------------------------------------
;自分の手番で自分の評価値の最大値を求める
;<d4.w:先読みの深さ
;<d6.b:自分の石
;<d7.b:相手の石
;<a3.l:α
;<a4.l:β
;>d0.l:評価値
;?d1-d2
.text
.align 4,$2048
eval_max:
tst.w d4
beq eval
movem.l d3-d4/a0-a1/a3/a5-a6,-(sp)
bsr list_ban ;自分が置ける位置のリストを作る
beq 5f ;どこにも置けない(パスまたは終局)
subq.w #1,d4 ;先読みの深さ
move.l (a1)+,d0
1: movea.l d0,a0
bsr put_record_one
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr eval_min ;相手の手番で自分の評価値の最小値を求める
exg.l d6,d7
cmp.l a3,d0
ble @f
movea.l d0,a3 ;αを更新
@@: bsr tup_record_one
cmpa.l a4,a3
bge 7f ;α>=βなのでβカット
move.l (a1)+,d0
bne 1b
98: move.l a3,d0 ;αを返す
99: movem.l (sp)+,d3-d4/a0-a1/a3/a5-a6
rts
;どこにも置けない(パスまたは終局)
5: exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr count_ban
beq 6f ;相手も置けないので終局
bsr eval_min ;相手の手番で自分の評価値の最小値を求める
exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bra 99b
;相手も置けないので終局
6: exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr get_sekisa
asl.w #8,d0 ;石差×256
ext.l d0
bra 99b
;α>=βなのでβカット
;親のαを返してはならない(評価値が同じだと選択されてしまうことがある)
7: move.l #$3FFFFFFF,d0 ;絶対に選択されない
bra 99b
;----------------------------------------------------------------
;相手の手番で自分の評価値の最小値を求める
;<d4.w:先読みの深さ
;<d6.b:相手の石
;<d7.b:自分の石
;<a3.l:α
;<a4.l:β
;>d0.l:評価値
;?d1-d2
.text
.align 4,$2048
@@: bsr eval
neg.l d0
rts
.align 4,$2048
eval_min:
tst.w d4
beq @b
movem.l d3-d4/a0-a1/a4/a5-a6,-(sp)
bsr list_ban ;相手が置ける位置のリストを作る
beq 5f ;どこにも置けない(パスまたは終局)
subq.w #1,d4 ;先読みの深さ
move.l (a1)+,d0
1: movea.l d0,a0
bsr put_record_one
exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr eval_max ;自分の手番で自分の評価値の最大値を求める
exg.l d6,d7
cmp.l a4,d0
bge @f
movea.l d0,a4 ;βを更新
@@: bsr tup_record_one
cmpa.l a3,a4
ble 7f ;β<=αなのでαカット
move.l (a1)+,d0
bne 1b
98: move.l a4,d0 ;βを返す
99: movem.l (sp)+,d3-d4/a0-a1/a4/a5-a6
rts
;どこにも置けない(パスまたは終局)
5: exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr count_ban
beq 6f ;自分も置けないので終局
bsr eval_max ;自分の手番で自分の評価値の最大値を求める
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bra 99b
;自分も置けないので終局
6: bsr get_sekisa
asl.w #8,d0 ;石差×256
ext.l d0
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bra 99b
;β<=αなのでαカット
;親のβを返してはならない(評価値が同じだと選択されてしまうことがある)
7: move.l #$C0000000,d0 ;絶対に選択されない
bra 99b
;----------------------------------------------------------------
;評価関数
;<d6.b:自分の石
;>d0.l:評価値
;?d1-d2
.text
.align 4,$2048
eval:
movem.l d3-d4/a0-a2,-(sp)
;スキャンマップを初期化する
lea.l map,a1
moveq.l #0,d0
.rept (BAN_LEN+3)/4
move.l d0,(a1)+
.endm
;スキャン(右)
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 2┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 3┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 4┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 5┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 6┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 7┃●─────────────→┃
; ┠─┼─┼─┼─┼─┼─┼─┼─┨
; 8┃●─────────────→┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
moveq.l #V5,d1
lea.l ban+P11,a0
bsr scan
lea.l ban+P12,a0
bsr scan
lea.l ban+P13,a0
bsr scan
lea.l ban+P14,a0
bsr scan
lea.l ban+P15,a0
bsr scan
lea.l ban+P16,a0
bsr scan
lea.l ban+P17,a0
bsr scan
lea.l ban+P18,a0
bsr scan
;スキャン(左下)
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃ │ │●│●│●│●│●│●┃
; ┠─┼─/─/─/─/─/─/─┨
; 2┃ │/│/│/│/│/│/│●┃
; ┠─/─/─/─/─/─/─/─┨
; 3┃/│/│/│/│/│/│/│●┃
; ┠─/─/─/─/─/─/─/─┨
; 4┃/│/│/│/│/│/│/│●┃
; ┠─/─/─/─/─/─/─/─┨
; 5┃/│/│/│/│/│/│/│●┃
; ┠─/─/─/─/─/─/─/─┨
; 6┃/│/│/│/│/│/│/│●┃
; ┠─/─/─/─/─/─/─/─┨
; 7┃/│/│/│/│/│/│/│ ┃
; ┠─/─/─/─/─/─/─┼─┨
; 8┃/│/│/│/│/│/│ │ ┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
moveq.l #V6,d1
lea.l ban+P31,a0
bsr scan
lea.l ban+P41,a0
bsr scan
lea.l ban+P51,a0
bsr scan
lea.l ban+P61,a0
bsr scan
lea.l ban+P71,a0
bsr scan
lea.l ban+P81,a0
bsr scan
lea.l ban+P82,a0
bsr scan
lea.l ban+P83,a0
bsr scan
lea.l ban+P84,a0
bsr scan
lea.l ban+P85,a0
bsr scan
lea.l ban+P86,a0
bsr scan
;スキャン(下)
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃●│●│●│●│●│●│●│●┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 2┃│││││││││││││││┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 3┃│││││││││││││││┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 4┃│││││││││││││││┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 5┃│││││││││││││││┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 6┃│││││││││││││││┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 7┃│││││││││││││││┃
; ┠│┼│┼│┼│┼│┼│┼│┼│┨
; 8┃↓│↓│↓│↓│↓│↓│↓│↓┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
moveq.l #V7,d1
lea.l ban+P11,a0
bsr scan
lea.l ban+P21,a0
bsr scan
lea.l ban+P31,a0
bsr scan
lea.l ban+P41,a0
bsr scan
lea.l ban+P51,a0
bsr scan
lea.l ban+P61,a0
bsr scan
lea.l ban+P71,a0
bsr scan
lea.l ban+P81,a0
bsr scan
;スキャン(右下)
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃●│●│●│●│●│●│ │ ┃
; ┠─\─\─\─\─\─\─┼─┨
; 2┃●│\│\│\│\│\│\│ ┃
; ┠─\─\─\─\─\─\─\─┨
; 3┃●│\│\│\│\│\│\│\┃
; ┠─\─\─\─\─\─\─\─┨
; 4┃●│\│\│\│\│\│\│\┃
; ┠─\─\─\─\─\─\─\─┨
; 5┃●│\│\│\│\│\│\│\┃
; ┠─\─\─\─\─\─\─\─┨
; 6┃●│\│\│\│\│\│\│\┃
; ┠─\─\─\─\─\─\─\─┨
; 7┃ │\│\│\│\│\│\│\┃
; ┠─┼─\─\─\─\─\─\─┨
; 8┃ │ │\│\│\│\│\│\┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
moveq.l #V8,d1
lea.l ban+P11,a0
bsr scan
lea.l ban+P21,a0
bsr scan
lea.l ban+P31,a0
bsr scan
lea.l ban+P41,a0
bsr scan
lea.l ban+P51,a0
bsr scan
lea.l ban+P61,a0
bsr scan
lea.l ban+P12,a0
bsr scan
lea.l ban+P13,a0
bsr scan
lea.l ban+P14,a0
bsr scan
lea.l ban+P15,a0
bsr scan
lea.l ban+P16,a0
bsr scan
;隅から辺へのスキャン
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃●─────────────→┃
; ┠│\─┼─┼─┼─┼─┼─┼─┨
; 2┃││\│ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 3┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 4┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 5┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 6┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 7┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 8┃↓│ │ │ │ │ │ │ ┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
lea.l ban+P11,a0
moveq.l #V5,d0
moveq.l #V7,d1
bsr scan_edge
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃←─────────────●┃
; ┠─┼─┼─┼─┼─┼─┼─/│┨
; 2┃ │ │ │ │ │ │/││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 3┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 4┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 5┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 6┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 7┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 8┃ │ │ │ │ │ │ │↓┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
lea.l ban+P81,a0
moveq.l #V4,d0
moveq.l #V7,d1
bsr scan_edge
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃↑│ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 2┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 3┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 4┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 5┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 6┃││ │ │ │ │ │ │ ┃
; ┠│┼─┼─┼─┼─┼─┼─┼─┨
; 7┃││/│ │ │ │ │ │ ┃
; ┠│/─┼─┼─┼─┼─┼─┼─┨
; 8┃●─────────────→┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
lea.l ban+P18,a0
moveq.l #V5,d0
moveq.l #V2,d1
bsr scan_edge
; 1 2 3 4 5 6 7 8
; ┏━┯━┯━┯━┯━┯━┯━┯━┓
; 1┃ │ │ │ │ │ │ │↑┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 2┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 3┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 4┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 5┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 6┃ │ │ │ │ │ │ ││┃
; ┠─┼─┼─┼─┼─┼─┼─┼│┨
; 7┃ │ │ │ │ │ │\││┃
; ┠─┼─┼─┼─┼─┼─┼─\│┨
; 8┃←─────────────●┃
; ┗━┷━┷━┷━┷━┷━┷━┷━┛
lea.l ban+P88,a0
moveq.l #V4,d0
moveq.l #V2,d1
bsr scan_edge
;スキャンマップをもとに評価を行う
moveq.l #0,d4 ;最下位バイト以外を0に固定
lea.l ban+P11,a0
suba.l a2,a2 ;評価値
moveq.l #P88-P11,d1
10: move.b (a0)+,d0
bmi 50f ;壁
bne 30f ;石がある
;空き
moveq.l #MAP_ICANPUT|MAP_YOUCANPUT,d3
and.b (map-ban-1,a0),d3
beq 50f ;空きでどちらも置けない
;空きで少なくともどちらかが置ける
move.b (yoyuu-ban-1,a0),d4
subq.b #MAP_ICANPUT,d3
bne @f
;空きで自分だけが置ける
adda.w d4,a2
bra 50f
@@: subq.b #MAP_YOUCANPUT-MAP_ICANPUT,d3
bne 50f ;空きで自分と相手の両方が置ける
;空きで相手だけが置ける
suba.w d4,a2
bra 50f
;石がある
30: cmp.b d6,d0
bne 40f ;相手の石がある
;自分の石がある
moveq.l #MAP_YOUCANGET,d3
and.b (map-ban-1,a0),d3
bne @f ;自分の石があって相手がひっくり返せる
;自分の石があって相手がひっくり返せない→自分の確定石
move.b (kakutei-ban-1,a0),d4
adda.w d4,a2
bra 50f
;自分の石があって相手がひっくり返せる
@@: move.b (kiken-ban-1,a0),d4
suba.w d4,a2
bra 50f
;相手の石がある
40: moveq.l #MAP_ICANGET,d3
and.b (map-ban-1,a0),d3
bne @f ;相手の石があって自分がひっくり返せる
;相手の石があって自分がひっくり返せない→相手の確定石
move.b (kakutei-ban-1,a0),d4
suba.w d4,a2
bra 50f
;相手の石があって自分がひっくり返せる
@@: move.b (kiken-ban-1,a0),d4
adda.w d4,a2
bra 50f
50:
dbra d1,10b
move.l a2,d0 ;評価値
movem.l (sp)+,d3-d4/a0-a2
rts
;----------------------------------------------------------------
;ラインスキャンを行う
; マスが3個以上あるラインを指定すること
;<d1.w:ベクタ
;<d6.b:自分の石
;<a0.l:開始位置(ban)
;?a1-a2
.text
.align 4,$2048
scan:
move.b (a0),d0
bne 19f ;石がある
;空き
10: movea.l a0,a1
adda.w d1,a0
move.b (a0),d0
bmi 99f ;空き→壁
beq 10b ;空き→空き
cmp.b d6,d0
bne 12f ;空き→相手の石
;空き→自分の石
11: movea.l a0,a2
adda.w d1,a0
move.b (a0),d0
bmi 99f ;空き→自分の石→壁
beq 10b ;空き→自分の石→空き
cmp.b d6,d0
beq 11b ;空き→自分の石→自分の石
;空き→自分の石→相手の石
ori.b #MAP_YOUCANPUT,(map-ban,a1)
adda.w d1,a1
@@: ori.b #MAP_YOUCANGET,(map-ban,a1)
adda.w d1,a1
cmpa.l a0,a1
bne @b
movea.l a2,a1
bra 21f ;自分の石→相手の石
;空き→相手の石
12: movea.l a0,a2
adda.w d1,a0
move.b (a0),d0
bmi 99f ;空き→相手の石→壁
beq 10b ;空き→相手の石→空き
cmp.b d6,d0
bne 12b ;空き→相手の石→相手の石
;空き→相手の石→自分の石
ori.b #MAP_ICANPUT,(map-ban,a1)
adda.w d1,a1
@@: ori.b #MAP_ICANGET,(map-ban,a1)
adda.w d1,a1
cmpa.l a0,a1
bne @b
movea.l a2,a1
bra 31f ;相手の石→自分の石
;石がある
19: cmp.b d6,d0
bne 30f ;相手の石
;自分の石
20: movea.l a0,a1
adda.w d1,a0
move.b (a0),d0
bmi 99f ;自分の石→壁
beq 10b ;自分の石→空き
cmp.b d6,d0
beq 20b ;自分の石→自分の石
;自分の石→相手の石
21: movea.l a0,a2
adda.w d1,a0
move.b (a0),d0
bmi 99f ;自分の石→相手の石→壁
beq 22f ;自分の石→相手の石→空き
cmp.b d6,d0
bne 21b ;自分の石→相手の石→相手の石
;自分の石→相手の石→自分の石
movea.l a2,a1
bra 31f ;相手の石→自分の石
;自分の石→相手の石→空き
22: adda.w d1,a1
@@: ori.b #MAP_ICANGET,(map-ban,a1)
adda.w d1,a1
cmpa.l a0,a1
bne @b
ori.b #MAP_ICANPUT,(map-ban,a0)
bra 10b
;相手の石
30: movea.l a0,a1
adda.w d1,a0
move.b (a0),d0
bmi 99f ;相手の石→壁
beq 10b ;相手の石→空き
cmp.b d6,d0
bne 30b ;相手の石→相手の石
;相手の石→自分の石
31: movea.l a0,a2
adda.w d1,a0
move.b (a0),d0
bmi 99f ;相手の石→自分の石→壁
beq 32f ;相手の石→自分の石→空き
cmp.b d6,d0
beq 31b ;相手の石→自分の石→自分の石
;相手の石→自分の石→相手の石
movea.l a2,a1
bra 21b ;自分の石→相手の石
;相手の石→自分の石→空き
32: adda.w d1,a1
@@: ori.b #MAP_YOUCANGET,(map-ban,a1)
adda.w d1,a1
cmpa.l a0,a1
bne @b
ori.b #MAP_YOUCANPUT,(map-ban,a0)
bra 10b
99: rts
;----------------------------------------------------------------
;隅から辺へのスキャン
; 辺は両方の隅からスキャンされるので,ここでは片方向だけスキャンすればよい
; 星もチェックする
;<a0.l:隅の位置
;<d0.w:辺のベクトル
;<d1.w:辺のベクトル
;<d6.b:自分の石
;<d7.b:相手の石
;?d2-d3/a1
.text
.align 4,$2048
scan_edge:
tst.b (a0)
bne 99f ;隅が空いていなければスキップ
;隅が空いていて星に石があるとき,星と隅をマークする
move.w d0,d2
add.w d1,d2 ;隅から星へのベクトル
move.b (a0,d2.w),d3 ;星
beq 2f ;星に石がない
cmp.b d6,d3
bne 1f ;隅が空いていて星に相手の石がある
;隅が空いていて星に自分の石がある
ori.b #MAP_YOUCANGET,(map-ban,a0,d2.w)
ori.b #MAP_YOUCANPUT,(map-ban,a0)
bra 2f
;隅が空いていて星に相手の石がある
1: ori.b #MAP_ICANGET,(map-ban,a0,d2.w)
ori.b #MAP_ICANPUT,(map-ban,a0)
2:
;隅が空いていて隣に石が5個まで連続してあるとき,その石と隅をマークする
move.b (a0,d0.w),d2 ;隣
beq 30f ;隣に石がない
;隅が空いていて隣に石がある
cmp.b d6,d2
bne 20f ;隅が空いていて隣に相手の石がある
;隅が空いていて隣に自分の石がある
moveq.l #MAP_YOUCANGET,d2
movea.l a0,a1
adda.w d0,a1
adda.w d0,a1
cmp.b (a1),d6
bne 11f ;隅が空いていて隣に自分の石が1個だけある
adda.w d0,a1
cmp.b (a1),d6
bne 12f ;隅が空いていて隣に自分の石が2個だけある
adda.w d0,a1
cmp.b (a1),d6
bne 13f ;隅が空いていて隣に自分の石が3個だけある
adda.w d0,a1
cmp.b (a1),d6
bne 14f ;隅が空いていて隣に自分の石が4個だけある
adda.w d0,a1
cmp.b (a1),d6
beq 30f ;隅が空いていて隣に自分の石が6個以上ある
;隅が空いていて隣に自分の石が5個だけある
suba.w d0,a1
cmp.b (a1,d1.w),d6
bne 30f ;隅が空いていて隣に自分の石が5個だけあるが,
;ウイングにはなっていない
;隅が空いていて隣に自分の石が5個だけあって,ウイングになっている
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が4個だけある
14: suba.w d0,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が3個だけある
13: suba.w d0,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が2個だけある
12: suba.w d0,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が1個だけある
11: suba.w d0,a1
or.b d2,(map-ban,a1)
ori.b #MAP_YOUCANPUT,(map-ban,a0)
bra 30f
;隅が空いていて隣に相手の石がある
20: moveq.l #MAP_ICANGET,d2
movea.l a0,a1
adda.w d0,a1
adda.w d0,a1
cmp.b (a1),d7
bne 11f ;隅が空いていて隣に相手の石が1個だけある
adda.w d0,a1
cmp.b (a1),d7
bne 12f ;隅が空いていて隣に相手の石が2個だけある
adda.w d0,a1
cmp.b (a1),d7
bne 13f ;隅が空いていて隣に相手の石が3個だけある
adda.w d0,a1
cmp.b (a1),d7
bne 14f ;隅が空いていて隣に相手の石が4個だけある
adda.w d0,a1
cmp.b (a1),d7
beq 30f ;隅が空いていて隣に相手の石が6個以上ある
;隅が空いていて隣に相手の石が5個だけある
suba.w d0,a1
cmp.b (a1,d1.w),d7
bne 30f ;隅が空いていて隣に相手の石が5個だけあるが,
;ウイングにはなっていない
;隅が空いていて隣に相手の石が5個だけあって,ウイングになっている
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が4個だけある
14: suba.w d0,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が3個だけある
13: suba.w d0,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が2個だけある
12: suba.w d0,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が1個だけある
11: suba.w d0,a1
or.b d2,(map-ban,a1)
ori.b #MAP_ICANPUT,(map-ban,a0)
; bra 30f
30:
;隅が空いていて隣に石が5個まで連続してあるとき,その石と隅をマークする
move.b (a0,d1.w),d2 ;隣
beq 30f ;隣に石がない
;隅が空いていて隣に石がある
cmp.b d6,d2
bne 20f ;隅が空いていて隣に相手の石がある
;隅が空いていて隣に自分の石がある
moveq.l #MAP_YOUCANGET,d2
movea.l a0,a1
adda.w d1,a1
adda.w d1,a1
cmp.b (a1),d6
bne 11f ;隅が空いていて隣に自分の石が1個だけある
adda.w d1,a1
cmp.b (a1),d6
bne 12f ;隅が空いていて隣に自分の石が2個だけある
adda.w d1,a1
cmp.b (a1),d6
bne 13f ;隅が空いていて隣に自分の石が3個だけある
adda.w d1,a1
cmp.b (a1),d6
bne 14f ;隅が空いていて隣に自分の石が4個だけある
adda.w d1,a1
cmp.b (a1),d6
beq 30f ;隅が空いていて隣に自分の石が6個以上ある
;隅が空いていて隣に自分の石が5個だけある
suba.w d1,a1
cmp.b (a1,d0.w),d6
bne 30f ;隅が空いていて隣に自分の石が5個だけあるが,
;ウイングにはなっていない
;隅が空いていて隣に自分の石が5個だけあって,ウイングになっている
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が4個だけある
14: suba.w d1,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が3個だけある
13: suba.w d1,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が2個だけある
12: suba.w d1,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に自分の石が1個だけある
11: suba.w d1,a1
or.b d2,(map-ban,a1)
ori.b #MAP_YOUCANPUT,(map-ban,a0)
bra 30f
;隅が空いていて隣に相手の石がある
20: moveq.l #MAP_ICANGET,d2
movea.l a0,a1
adda.w d1,a1
adda.w d1,a1
cmp.b (a1),d7
bne 11f ;隅が空いていて隣に相手の石が1個だけある
adda.w d1,a1
cmp.b (a1),d7
bne 12f ;隅が空いていて隣に相手の石が2個だけある
adda.w d1,a1
cmp.b (a1),d7
bne 13f ;隅が空いていて隣に相手の石が3個だけある
adda.w d1,a1
cmp.b (a1),d7
bne 14f ;隅が空いていて隣に相手の石が4個だけある
adda.w d1,a1
cmp.b (a1),d7
beq 30f ;隅が空いていて隣に相手の石が6個以上ある
;隅が空いていて隣に相手の石が5個だけある
suba.w d1,a1
cmp.b (a1,d0.w),d7
bne 30f ;隅が空いていて隣に相手の石が5個だけあるが,
;ウイングにはなっていない
;隅が空いていて隣に相手の石が5個だけあって,ウイングになっている
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が4個だけある
14: suba.w d1,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が3個だけある
13: suba.w d1,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が2個だけある
12: suba.w d1,a1
***** or.b d2,(map-ban,a1)
;隅が空いていて隣に相手の石が1個だけある
11: suba.w d1,a1
or.b d2,(map-ban,a1)
ori.b #MAP_ICANPUT,(map-ban,a0)
; bra 30f
30:
99: rts
;----------------------------------------------------------------
;自分の石を置ける位置のリストを作る
;<d6.b:自分の石
;<d7.b:相手の石
;<a5.l:置ける位置のリストの先頭
;>d0.l:置ける位置の数(0=どこにも置けない=パスまたは終局)
;>a1.l:置ける位置のリストの先頭
;>a5.l:置ける位置のリストの末尾(0の直後)
;>z-flag:eq=どこにも置けない=パスまたは終局
.text
.align 4,$2048
list_ban:
movem.l d1/a2,-(sp)
movea.l a5,a1 ;置ける位置のリストの先頭
moveq.l #0,d1 ;置ける位置の数
lea.l (put_count_table,pc),a2
move.l (a2)+,d0
1: movea.l d0,a0
tst.b (a0)
bne 2f ;石がある
bsr put_test_ban
beq 2f ;置けない
addq.w #1,d1 ;置ける位置をカウント
move.l a0,(a5)+ ;置ける位置のリストに加える
2: move.l (a2)+,d0
bne 1b
clr.l (a5)+ ;置ける位置のリストの末尾
move.l d1,d0
movem.l (sp)+,d1/a2
rts
;----------------------------------------------------------------
;自分の石を置ける位置を数える
;<d6.b:自分の石
;<d7.b:相手の石
;>d0.l:置ける位置の数(0=どこにも置けない=パスまたは終局)
;>z-flag:eq=どこにも置けない=パスまたは終局
.text
.align 4,$2048
count_ban::
movem.l d1/a0/a2,-(sp)
moveq.l #0,d1 ;置ける位置の数
lea.l (put_count_table,pc),a2
move.l (a2)+,d0
1: movea.l d0,a0
tst.b (a0)
bne 2f
bsr put_test_ban
beq 2f
addq.w #1,d1 ;置ける位置をカウント
2: move.l (a2)+,d0
bne 1b
move.l d1,d0
movem.l (sp)+,d1/a0/a2
rts
;----------------------------------------------------------------
.text
.align 4,$2048
put_count_table:
.dc.l ban+P11,ban+P81,ban+P18,ban+P88 ;隅
.dc.l ban+P43,ban+P53,ban+P34,ban+P64 ;ボックスフィールド
.dc.l ban+P35,ban+P65,ban+P46,ban+P56
.dc.l ban+P42,ban+P52,ban+P24,ban+P74 ;Bの頭
.dc.l ban+P25,ban+P75,ban+P47,ban+P57
.dc.l ban+P33,ban+P63,ban+P36,ban+P66 ;ボックスコーナー
.dc.l ban+P31,ban+P61,ban+P13,ban+P83 ;A
.dc.l ban+P16,ban+P86,ban+P38,ban+P68
.dc.l ban+P32,ban+P62,ban+P23,ban+P73 ;Aの頭
.dc.l ban+P26,ban+P76,ban+P37,ban+P67
.dc.l ban+P41,ban+P51,ban+P14,ban+P84 ;B
.dc.l ban+P15,ban+P85,ban+P48,ban+P58
.dc.l ban+P21,ban+P71,ban+P12,ban+P82 ;C
.dc.l ban+P17,ban+P87,ban+P28,ban+P78
.dc.l ban+P22,ban+P72,ban+P27,ban+P77 ;星
.dc.l 0
;----------------------------------------------------------------
;指定された位置に自分の石を置く
;<d6.b:自分の石
;<d7.b:相手の白
;<a0.l:置く位置(空いているマスを指定すること)
;>d0.w:ひっくり返せる石の数,0でなければ石を置ける
;>z-flag:eq=置けない,ne=置ける
.text
.align 4,$2048
put_one:
moveq.l #0,d0 ;ひっくり返せる石の数
.irp vect,V1,V2,V3,V4,V5,V6,V7,V8
cmp.b (vect*1,a0),d7
bne 20f ;隣が相手の石でないのでひっくり返せない
cmp.b (vect*2,a0),d7
bne 11f ;相手の石が1個だけ繋がっている
cmp.b (vect*3,a0),d7
bne 12f ;相手の石が2個だけ繋がっている
cmp.b (vect*4,a0),d7
bne 13f ;相手の石が3個だけ繋がっている
cmp.b (vect*5,a0),d7
bne 14f ;相手の石が4個だけ繋がっている
cmp.b (vect*6,a0),d7
bne 15f ;相手の石が5個だけ繋がっている
bra 16f ;相手の石が6個以上繋がっている
;相手の石が1個だけ繋がっている
11: cmp.b (vect*2,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #1,d0
bra 21f
;相手の石が2個だけ繋がっている
12: cmp.b (vect*3,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #2,d0
bra 22f
;相手の石が3個だけ繋がっている
13: cmp.b (vect*4,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #3,d0
bra 23f
;相手の石が4個だけ繋がっている
14: cmp.b (vect*5,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #4,d0
bra 24f
;相手の石が5個だけ繋がっている
15: cmp.b (vect*6,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #5,d0
bra 25f
;相手の石が6個以上繋がっている
16: cmp.b (vect*7,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #6,d0
26: move.b d6,(vect*6,a0)
25: move.b d6,(vect*5,a0)
24: move.b d6,(vect*4,a0)
23: move.b d6,(vect*3,a0)
22: move.b d6,(vect*2,a0)
21: move.b d6,(vect*1,a0)
20:
.endm
tst.w d0
beq @f
move.b d6,(a0)
tst.w d0
@@:
rts
;----------------------------------------------------------------
;指定された位置に自分の石を置いて変化した位置をレコードに記録する
;<d6.b:自分の石
;<d7.b:相手の石
;<a0.l:置く位置(空いているマスを指定すること)
;<a6.l:レコードの末尾(上位から下位に向かって記録する)
;>d0.w:ひっくり返せる石の数,0でなければ石を置ける
;>a6.l:レコードの先頭
; 0.w ひっくり返した石の数
; 2.l 置いた位置(アドレス,置く前は空いていた)
; 6.b 置いた石
; 7.b ひっくり返した石
; 8.w ひっくり返した石の位置(置いた位置からのオフセット)
; :
;>z-flag:eq=置けない,ne=置ける
.text
.align 4,$2048
put_record_one::
moveq.l #0,d0 ;ひっくり返せる石の数
.irp vect,V1,V2,V3,V4,V5,V6,V7,V8
cmp.b (vect*1,a0),d7
bne 20f ;隣が相手の石でないのでひっくり返せない
cmp.b (vect*2,a0),d7
bne 11f ;相手の石が1個だけ繋がっている
cmp.b (vect*3,a0),d7
bne 12f ;相手の石が2個だけ繋がっている
cmp.b (vect*4,a0),d7
bne 13f ;相手の石が3個だけ繋がっている
cmp.b (vect*5,a0),d7
bne 14f ;相手の石が4個だけ繋がっている
cmp.b (vect*6,a0),d7
bne 15f ;相手の石が5個だけ繋がっている
bra 16f ;相手の石が6個以上繋がっている
;相手の石が1個だけ繋がっている
11: cmp.b (vect*2,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #1,d0
bra 21f
;相手の石が2個だけ繋がっている
12: cmp.b (vect*3,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #2,d0
bra 22f
;相手の石が3個だけ繋がっている
13: cmp.b (vect*4,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #3,d0
bra 23f
;相手の石が4個だけ繋がっている
14: cmp.b (vect*5,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #4,d0
bra 24f
;相手の石が5個だけ繋がっている
15: cmp.b (vect*6,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #5,d0
bra 25f
;相手の石が6個以上繋がっている
16: cmp.b (vect*7,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #6,d0
26: move.b d6,(vect*6,a0)
move.w #vect*6,-(a6)
25: move.b d6,(vect*5,a0)
move.w #vect*5,-(a6)
24: move.b d6,(vect*4,a0)
move.w #vect*4,-(a6)
23: move.b d6,(vect*3,a0)
move.w #vect*3,-(a6)
22: move.b d6,(vect*2,a0)
move.w #vect*2,-(a6)
21: move.b d6,(vect*1,a0)
move.w #vect*1,-(a6)
20:
.endm
tst.w d0
beq @f
move.b d6,(a0)
move.b d7,-(a6) ;ひっくり返した石
move.b d6,-(a6) ;置いた石
move.l a0,-(a6) ;置いた位置
move.w d0,-(a6) ;ひっくり返した石の数
@@:
rts
;----------------------------------------------------------------
;置いた石を元に戻す
;<a6.l:レコードの先頭
; 0.w ひっくり返した石の数
; 2.l 置いた位置(アドレス,置く前は空いていた)
; 6.b 置いた石
; 7.b ひっくり返した石
; 8.w ひっくり返した石の位置(置いた位置からのオフセット)
; :
;>a6.l:レコードの末尾
;?d0-d2/a0
.text
.align 4,$2048
tup_record_one:
move.w (a6)+,d1 ;ひっくり返した石の数
movea.l (a6)+,a0 ;置いた位置
move.w (a6)+,d2 ;下位バイト=ひっくり返した石
subq.w #1,d1
@@: move.w (a6)+,d0 ;ひっくり返した石の位置
move.b d2,(a0,d0.w)
dbra d1,@b
sf.b (a0) ;置いた位置
rts
;----------------------------------------------------------------
;指定された位置に自分の石を置けるか調べる
;<d6.b:自分の石
;<d7.b:相手の石
;<a0.l:置く位置(空いているマスを指定すること)
;>d0.w:ひっくり返せる石の数,0でなければ石を置ける
;>z-flag:eq=置けない,ne=置ける
.text
.align 4,$2048
put_test_ban:
moveq.l #0,d0 ;ひっくり返せる石の数
.irp vect,V1,V2,V3,V4,V5,V6,V7,V8
cmp.b (vect*1,a0),d7
bne 20f ;隣が相手の石でないのでひっくり返せない
cmp.b (vect*2,a0),d7
bne 11f ;相手の石が1個だけ繋がっている
cmp.b (vect*3,a0),d7
bne 12f ;相手の石が2個だけ繋がっている
cmp.b (vect*4,a0),d7
bne 13f ;相手の石が3個だけ繋がっている
cmp.b (vect*5,a0),d7
bne 14f ;相手の石が4個だけ繋がっている
cmp.b (vect*6,a0),d7
bne 15f ;相手の石が5個だけ繋がっている
bra 16f ;相手の石が6個以上繋がっている
;相手の石が1個だけ繋がっている
11: cmp.b (vect*2,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #1,d0
bra 21f
;相手の石が2個だけ繋がっている
12: cmp.b (vect*3,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #2,d0
bra 22f
;相手の石が3個だけ繋がっている
13: cmp.b (vect*4,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #3,d0
bra 23f
;相手の石が4個だけ繋がっている
14: cmp.b (vect*5,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #4,d0
bra 24f
;相手の石が5個だけ繋がっている
15: cmp.b (vect*6,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #5,d0
bra 25f
;相手の石が6個以上繋がっている
16: cmp.b (vect*7,a0),d6
bne 20f ;自分の石で終わっていないのでひっくり返せない
addq.w #6,d0
26:
25:
24:
23:
22:
21:
20:
.endm
tst.w d0
rts
;----------------------------------------------------------------
;定石探索
;<d6.b:自分の石
;<d7.b:相手の石
;<a6.l:レコードの末尾(上位から下位に向かって記録する)
;>d0.l:次の手(0=定石と一致しない)
;>z-flag:eq=定石と一致しない
.text
.align 4,$2048
joseki:
cmpi.w #50,aki_count
bhs @f
moveq.l #0,d0
rts
@@:
movem.l d1-d7/a0-a6,-(sp)
move.b d6,d5 ;自分の石
;定石探索用の盤を初期状態にセットする
lea.l sban,a0
lea.l jban0,a3
lea.l (jban2-jban0,a3),a4
moveq.l #(BAN_LEN+3)/4-1,d1
1: move.l (a0)+,d0
move.l d0,(a3)+
move.l d0,(jban1-jban0-4,a3)
move.l d0,(a4)+
move.l d0,(jban3-jban2-4,a4)
dbra d1,1b
;定石の探索を行う
moveq.l #B,d6
moveq.l #W,d7
lea.l (jlist_01,pc),a2 ;定石データ
lea.l jban0,a3
lea.l (jban2-jban0,a3),a4
movea.l sp,a5
bsr joseki_sub
moveq.l #0,d0
joseki_exit:
movem.l (sp)+,d1-d7/a0-a6 ;レコードの末尾も復元すること
rts
@@: rts
joseki_sub:
10: moveq.l #0,d2 ;上位ワードを0にしておく
move.w (a2)+,d2 ;X座標(1~8)
beq @b
moveq.l #0,d3 ;上位ワードを0にしておく
move.w (a2)+,d3 ;Y座標(1~8)
cmp.b d5,d6
bne 40f ;自分の番でなければ一致しないので比較を省略
;定石通りに生成した盤と比較する
lea.l ban,a0
movea.l a3,a1
bsr compare_ban
bne 30f
;そのままの盤と一致した
move.l d2,d0 ;そのまま
move.l d3,d1
;定石通りに生成した盤と一致した
;<d0.w:X座標
;<d1.w:Y座標
20: add.w d1,d0
lsl.w #3,d1
add.w d1,d0
movea.l a5,sp
bra joseki_exit
30:
lea.l ban,a0
lea.l (jban1-jban0,a3),a1
bsr compare_ban
bne 30f
;XとYを入れ替えた盤と一致した
move.l d3,d0 ;XとYを入れ替える
move.l d2,d1
bra 20b
30:
lea.l ban,a0
movea.l a4,a1
bsr compare_ban
bne 30f
;XとYをそれぞれ反転した盤と一致した
moveq.l #9,d0 ;XとYをそれぞれ反転する
moveq.l #9,d1
sub.w d2,d0
sub.w d3,d1
bra 20b
30:
lea.l ban,a0
lea.l (jban3-jban2,a4),a1
bsr compare_ban
bne 30f
;XとYをそれぞれ反転した上でXとYを入れ替えた盤と一致した
moveq.l #9,d0 ;XとYをそれぞれ反転した上でXとYを入れ替える
moveq.l #9,d1
sub.w d3,d0
sub.w d2,d1
bra 20b
30:
;定石通りに生成した盤と一致しなかった
40:
;定石通りに盤を更新する
move.l (a2)+,d4
beq 10b ;次の手がないので更新する必要がない
move.l d2,d0 ;そのまま
move.l d3,d1
add.w d1,d0
lsl.w #3,d1
add.w d1,d0
lea.l (a3,d0.w),a0
bsr put_record_one
.ifdef DEBUG
beq main_exit
.endif
move.l d3,d0 ;XとYを入れ替える
move.l d2,d1
add.w d1,d0
lsl.w #3,d1
add.w d1,d0
lea.l (jban1-jban0,a3,d0.w),a0
bsr put_record_one
.ifdef DEBUG
beq main_exit
.endif
moveq.l #9,d0 ;XとYをそれぞれ反転する
moveq.l #9,d1
sub.w d2,d0
sub.w d3,d1
add.w d1,d0
lsl.w #3,d1
add.w d1,d0
lea.l (a4,d0.w),a0
bsr put_record_one
.ifdef DEBUG
beq main_exit
.endif
moveq.l #9,d0 ;XとYをそれぞれ反転した上でXとYを入れ替える
moveq.l #9,d1
sub.w d3,d0
sub.w d2,d1
add.w d1,d0
lsl.w #3,d1
add.w d1,d0
lea.l (jban3-jban2,a4,d0.w),a0
bsr put_record_one
.ifdef DEBUG
beq main_exit
.endif
exg.l d6,d7
move.l a2,-(sp)
movea.l d4,a2 ;次の手へ(0は既に除外してある)
bsr joseki_sub
movea.l (sp)+,a2
exg.l d6,d7
bsr tup_record_one
bsr tup_record_one
bsr tup_record_one
bsr tup_record_one
bra 10b
;定石データ
; 牛 3 4 5 6
; 6 3
; ●○ 4
; 5○●1 5
; 432 6
;
; 兎 3 4 5 6
; 5 3
; ●○4 4
; 3○●1 5
; 2 6
;
; 鼠 3 4 5 6
; 3 3
; ●○2 4
; 5○●1 5
; 4 6
.even
jlist_01: .dc.w 6,5,jlist_02.l
.dc.w 0
jlist_02: .dc.w 6,6,jlist_13.l ;牛
.dc.w 4,6,jlist_23.l ;兎
.dc.w 6,4,jlist_33.l ;鼠
.dc.w 0
;牛
jlist_13: .dc.w 5,6,jlist_14.l
.dc.w 0
jlist_14: .dc.w 4,6,jlist_15.l
.dc.w 0
jlist_15: .dc.w 3,5,jlist_16.l
.dc.w 0
jlist_16: .dc.w 5,3,0.l
.dc.w 0
;兎
jlist_23: .dc.w 3,5,jlist_24.l
.dc.w 0
jlist_24: .dc.w 6,4,jlist_25.l
.dc.w 0
jlist_25: .dc.w 5,3,0.l
.dc.w 0
;鼠
jlist_33: .dc.w 5,3,jlist_34.l
.dc.w 0
jlist_34: .dc.w 4,6,jlist_35.l
.dc.w 0
jlist_35: .dc.w 3,5,0.l
.dc.w 0
.bss
.align 4
jban0: .ds.b BAN_LEN
.align 4
jban1: .ds.b BAN_LEN
.align 4
jban2: .ds.b BAN_LEN
.align 4
jban3: .ds.b BAN_LEN
.align 4
;----------------------------------------------------------------
;盤を比較する
;<a0.l:盤の先頭(4の倍数)
;<a1.l:盤の先頭(4の倍数)
;z-flag:eq=一致,ne=不一致
;?a0-a1
.text
.align 4,$2048
compare_ban:
lea.l ((P11/4)*4,a0),a0
lea.l ((P11/4)*4,a1),a1
.rept ((P88+3)/4)-(P11/4) ;P88+3までは壁があるので盤からはみ出すことはない
cmpm.l (a0)+,(a1)+
bne @f
.endm
@@: rts
;----------------------------------------------------------------
;終盤の読み切り
; 置ける場所がある状態で呼び出すこと
;<d6.b:自分の石
;<d7.b:相手の石
;<a5.l:置ける位置のリストの先頭
;<a6.l:レコードの末尾(上位から下位に向かって記録する)
;>d0.l:次の手(0=定石と一致しない)
;>z-flag:eq=定石と一致しない
.text
.align 4,$2048
yomikiri:
move.w aki_count,d0
cmp.w hisshou_level,d0
bls @f
moveq.l #0,d0
rts
@@:
movem.l d1-d7/a0-a6,-(sp)
;自分が置ける場所のリストを作る
bsr list_ban
lea.l eval_list,a2 ;リストの先頭(評価値が大きい順に並べる)
movea.l a2,a3
clr.l (a3)+ ;置く位置(番兵なので0)
clr.l (a3)+ ;次のセルへのポインタ(番兵なので無効)
move.l #$80000000,(a3)+ ;評価値(番兵なので最小値)
move.l (a1)+,d0 ;置く位置
1: movea.l d0,a0 ;置く位置
move.l a0,(a3) ;置く位置
bsr put_record_one
exg.l d6,d7
bsr eval ;評価してみる
exg.l d6,d7
neg.l d0
move.l d0,(8,a3) ;評価値
movea.l a2,a0 ;リストの先頭
bra 16f
15: movea.l a0,a4 ;直前のセルへのポインタ
movea.l (4,a0),a0
16: cmp.l (8,a0),d0 ;評価値を比較
ble 15b
move.l a0,(4,a3) ;次のセルへのポインタ
cmpa.l a2,a0
beq 17f
move.l a3,(4,a4) ;直前のセルの次のセルへのポインタを更新する
bra 18f
17: movea.l a3,a2 ;リストの先頭を更新する
18: lea.l (12,a3),a3 ;次の空きセル
bsr tup_record_one
move.l (a1)+,d0 ;置く位置
bne 1b
;石差と空きマス数を確認する
bsr get_sekisa
move.w d0,d5 ;石差(自分の石の数-相手の石の数)
move.w aki_count,d4 ;空きマス数
subq.w #1,d4 ;最初の手の分
;α-β法で枝狩りしながら終局まで読み切る
;必勝読み切りなので石差が1以上になる手が見つかったら終わり
movea.w #$8000,a3 ;α
movea.w #$7FFF,a4 ;β
movea.l a2,a1 ;置く位置のリストの先頭
move.w aki_count,d0
cmp.w kanzen_level,d0
bls kanzen ;完全読み切りを行う
.if 0
moveq.l #16,d0
moveq.l #0,d1
bsr locate
moveq.l #'*',d0
bsr putchar
moveq.l #100,d0
bsr wait_sec
.endif
move.l (a1)+,d0 ;置く位置
1: movea.l d0,a0 ;置く位置
bsr put_record_one
add.w d0,d5
add.w d0,d5
addq.w #1,d5
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr hisshou_min ;相手の手番で自分の石差の最小値を求める
exg.l d6,d7
cmp.w a3,d0
ble @f
movea.l a0,a2 ;相手の手番で自分の石差の最小値が最大になる手
tst.w d0
bgt 3f ;必勝読み切りのときは,
;石差が1以上になる手が見つかったら終わり
movea.w d0,a3 ;αを更新
@@: move.w (a6),d0
subq.w #1,d5
sub.w d0,d5
sub.w d0,d5
bsr tup_record_one
2: movea.l (a1)+,a1 ;次のセルへのポインタ(最後に番兵が出てくる)
move.l (a1)+,d0 ;置く位置(番兵のセルは0)
bne 1b
;必勝読み切りで石差が1以上になる手が見つからなかったときは,
;石差がなるべく大きくなる手を選ぶ
98: move.l a2,d0
sub.l #ban,d0
99: movem.l (sp)+,d1-d7/a0-a6
rts
3: move.w (a6),d0
subq.w #1,d5
sub.w d0,d5
sub.w d0,d5
bsr tup_record_one
bra 98b
;完全読み切りを行う
kanzen:
.if 0
moveq.l #16,d0
moveq.l #0,d1
bsr locate
moveq.l #'!',d0
bsr putchar
moveq.l #100,d0
bsr wait_sec
.endif
move.l (a1)+,d0 ;置く位置
1: movea.l d0,a0 ;置く位置
bsr put_record_one
add.w d0,d5
add.w d0,d5
addq.w #1,d5
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr kanzen_min ;相手の手番で自分の石差の最小値を求める
exg.l d6,d7
cmp.w a3,d0
ble @f
movea.l a0,a2 ;相手の手番で自分の石差の最小値が最大になる手
movea.w d0,a3 ;αを更新
@@: move.w (a6),d0
subq.w #1,d5
sub.w d0,d5
sub.w d0,d5
bsr tup_record_one
2: movea.l (a1)+,a1 ;次のセルへのポインタ(最後に番兵が出てくる)
move.l (a1)+,d0 ;置く位置(番兵のセルは0)
bne 1b
;石差がなるべく大きくなる手を選ぶ
move.l a2,d0
sub.l #ban,d0
99: movem.l (sp)+,d1-d7/a0-a6
rts
;----------------------------------------------------------------
;自分の手番で自分の石差の最大値を求める(必勝読み切り)
;<d4.w:空きマス数
;<d5.w:石差(自分の石の数-相手の石の数)
;<d6.b:自分の石
;<d7.b:相手の石
;<a3.l:α
;<a4.l:β
;>d0.w:石差(自分の石の数-相手の石の数)
.text
.align 4,$2048
@@: move.w d5,d0 ;石差(自分の石の数-相手の石の数)
rts
.align 4,$2048
hisshou_max:
tst.w d4
beq @b
movem.l d3-d4/a0-a1/a3/a5-a6,-(sp)
bsr list_ban ;自分が置ける位置のリストを作る
beq 5f ;どこにも置けない(パスまたは終局)
subq.w #1,d4
move.l (a1)+,d0
1: movea.l d0,a0
bsr put_record_one
add.w d0,d5
add.w d0,d5
addq.w #1,d5
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr hisshou_min ;相手の手番で自分の石差の最小値を求める
exg.l d6,d7
cmp.w a3,d0
ble @f
movea.w d0,a3 ;αを更新
tst.w d0
bgt 3f ;必勝読み切りのときは,
;石差が1以上になる手が見つかったら終わり
@@: move.w (a6),d0
subq.w #1,d5
sub.w d0,d5
sub.w d0,d5
bsr tup_record_one
cmpa.l a4,a3
bge 7f ;α>=βなのでβカット
2: move.l (a1)+,d0
bne 1b
98: move.w a3,d0 ;αを返す
99: movem.l (sp)+,d3-d4/a0-a1/a3/a5-a6
rts
3: move.w (a6),d0
subq.w #1,d5
sub.w d0,d5
sub.w d0,d5
bsr tup_record_one
bra 98b
;どこにも置けない(パスまたは終局)
5: exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr count_ban
beq 6f ;相手も置けないので終局
bsr hisshou_min ;相手の手番で自分の石差の最小値を求める
exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bra 99b
;相手も置けないので終局
6: exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
move.w d5,d0 ;石差
bra 99b
;α>=βなのでβカット
;親のαを返してはならない(評価値が同じだと選択されてしまうことがある)
7: move.w #$3FFF,d0 ;絶対に選択されない
bra 99b
;----------------------------------------------------------------
;相手の手番で自分の石差の最小値を求める(必勝読み切り)
;<d4.w:空きマス数
;<d5.w:石差(自分の石の数-相手の石の数)
;<d6.b:相手の石
;<d7.b:自分の石
;<a3.l:α
;<a4.l:β
;>d0.w:石差(自分の石の数-相手の石の数)
.text
.align 4,$2048
@@: move.w d5,d0 ;石差(自分の石の数-相手の石の数)
rts
.align 4,$2048
hisshou_min:
tst.w d4
beq @b
movem.l d3-d4/a0-a1/a4/a5-a6,-(sp)
bsr list_ban ;自分が置ける位置のリストを作る
beq 5f ;どこにも置けない(パスまたは終局)
subq.w #1,d4
move.l (a1)+,d0
1: movea.l d0,a0
bsr put_record_one
sub.w d0,d5
sub.w d0,d5
subq.w #1,d5
exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr hisshou_max ;自分の手番で自分の石差の最大値を求める
exg.l d6,d7
cmp.w a4,d0
bge @f
movea.w d0,a4 ;βを更新
@@: move.w (a6),d0
addq.w #1,d5
add.w d0,d5
add.w d0,d5
bsr tup_record_one
cmpa.l a3,a4
ble 7f ;β<=αなのでαカット
2: move.l (a1)+,d0
bne 1b
98: move.w a4,d0 ;βを返す
99: movem.l (sp)+,d3-d4/a0-a1/a4/a5-a6
rts
;どこにも置けない(パスまたは終局)
5: exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr count_ban
beq 6f ;自分も置けないので終局
bsr hisshou_max ;自分の手番で自分の石差の最大値を求める
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bra 99b
;自分も置けないので終局
6: move.w d5,d0 ;石差
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bra 99b
;β<=αなのでαカット
;親のβを返してはならない(評価値が同じだと選択されてしまうことがある)
7: move.w #$C000,d0 ;絶対に選択されない
bra 99b
;----------------------------------------------------------------
;自分の手番で自分の石差の最大値を求める(完全読み切り)
;<d4.w:空きマス数
;<d5.w:石差(自分の石の数-相手の石の数)
;<d6.b:自分の石
;<d7.b:相手の石
;<a3.l:α
;<a4.l:β
;>d0.w:石差(自分の石の数-相手の石の数)
.text
.align 4,$2048
@@: move.w d5,d0 ;石差(自分の石の数-相手の石の数)
rts
.align 4,$2048
kanzen_max:
tst.w d4
beq @b
movem.l d3-d4/a0-a1/a3/a5-a6,-(sp)
bsr list_ban ;自分が置ける位置のリストを作る
beq 5f ;どこにも置けない(パスまたは終局)
subq.w #1,d4
move.l (a1)+,d0
1: movea.l d0,a0
bsr put_record_one
add.w d0,d5
add.w d0,d5
addq.w #1,d5
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr kanzen_min ;相手の手番で自分の石差の最小値を求める
exg.l d6,d7
cmp.w a3,d0
ble @f
movea.w d0,a3 ;αを更新
@@: move.w (a6),d0
subq.w #1,d5
sub.w d0,d5
sub.w d0,d5
bsr tup_record_one
cmpa.l a4,a3
bge 7f ;α>=βなのでβカット
2: move.l (a1)+,d0
bne 1b
98: move.w a3,d0 ;αを返す
99: movem.l (sp)+,d3-d4/a0-a1/a3/a5-a6
rts
;どこにも置けない(パスまたは終局)
5: exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bsr count_ban
beq 6f ;相手も置けないので終局
bsr kanzen_min ;相手の手番で自分の石差の最小値を求める
exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bra 99b
;相手も置けないので終局
6: exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
move.w d5,d0 ;石差
bra 99b
;α>=βなのでβカット
;親のαを返してはならない(評価値が同じだと選択されてしまうことがある)
7: move.w #$3FFF,d0 ;絶対に選択されない
bra 99b
;----------------------------------------------------------------
;相手の手番で自分の石差の最小値を求める(完全読み切り)
;<d4.w:空きマス数
;<d5.w:石差(自分の石の数-相手の石の数)
;<d6.b:相手の石
;<d7.b:自分の石
;<a3.l:α
;<a4.l:β
;>d0.w:石差(自分の石の数-相手の石の数)
.text
.align 4,$2048
@@: move.w d5,d0 ;石差(自分の石の数-相手の石の数)
rts
.align 4,$2048
kanzen_min:
tst.w d4
beq @b
movem.l d3-d4/a0-a1/a4/a5-a6,-(sp)
bsr list_ban ;自分が置ける位置のリストを作る
beq 5f ;どこにも置けない(パスまたは終局)
subq.w #1,d4
move.l (a1)+,d0
1: movea.l d0,a0
bsr put_record_one
sub.w d0,d5
sub.w d0,d5
subq.w #1,d5
exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr kanzen_max ;自分の手番で自分の石差の最大値を求める
exg.l d6,d7
cmp.w a4,d0
bge @f
movea.w d0,a4 ;βを更新
@@: move.w (a6),d0
addq.w #1,d5
add.w d0,d5
add.w d0,d5
bsr tup_record_one
cmpa.l a3,a4
ble 7f ;β<=αなのでαカット
2: move.l (a1)+,d0
bne 1b
98: move.w a4,d0 ;βを返す
99: movem.l (sp)+,d3-d4/a0-a1/a4/a5-a6
rts
;どこにも置けない(パスまたは終局)
5: exg.l d6,d7
;<d6.b:自分の石
;<d7.b:相手の石
bsr count_ban
beq 6f ;自分も置けないので終局
bsr kanzen_max ;自分の手番で自分の石差の最大値を求める
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bra 99b
;自分も置けないので終局
6: move.w d5,d0 ;石差
exg.l d6,d7
;<d6.b:相手の石
;<d7.b:自分の石
bra 99b
;β<=αなのでαカット
;親のβを返してはならない(評価値が同じだと選択されてしまうことがある)
7: move.w #$C000,d0 ;絶対に選択されない
bra 99b
;----------------------------------------------------------------
.data
;盤の初期状態
.align 4
sban:
; 1 2 3 4 5 6 7 8
.dc.b _,_,_,_,_,_,_,_,_
.dc.b _,S,S,S,S,S,S,S,S ;1
.dc.b _,S,S,S,S,S,S,S,S ;2
.dc.b _,S,S,S,S,S,S,S,S ;3
.dc.b _,S,S,S,W,B,S,S,S ;4
.dc.b _,S,S,S,B,W,S,S,S ;5
.dc.b _,S,S,S,S,S,S,S,S ;6
.dc.b _,S,S,S,S,S,S,S,S ;7
.dc.b _,S,S,S,S,S,S,S,S ;8
.dc.b _,_,_,_,_,_,_,_,_,_
.align 4
;現在の盤
.align 4
ban::
; 1 2 3 4 5 6 7 8
.dc.b _,_,_,_,_,_,_,_,_
.dc.b _,S,S,S,S,S,S,S,S ;1
.dc.b _,S,S,S,S,S,S,S,S ;2
.dc.b _,S,S,S,S,S,S,S,S ;3
.dc.b _,S,S,S,W,B,S,S,S ;4
.dc.b _,S,S,S,B,W,S,S,S ;5
.dc.b _,S,S,S,S,S,S,S,S ;6
.dc.b _,S,S,S,S,S,S,S,S ;7
.dc.b _,S,S,S,S,S,S,S,S ;8
.dc.b _,_,_,_,_,_,_,_,_,_
.align 4
;スキャンマップ
; スキャンマップはbanから8ビットオフセットで届く位置に配置すること
.align 4
map: .dcb.b BAN_LEN,0
.align 4
;得点表
; 固定データだが、banからの相対アドレスで参照しやすいように.dataに配置する
; 星の危険石>辺の危険石>中央の余裕手>辺の確定石>辺の余裕手
; 辺5~6石確定>ウイングの減点
;余裕手(空きで自分だけ置ける)の得点
yoyuu: .dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0
.if 0
.dc.b 0,255, 0, 20, 18, 18, 20, 0,255
.dc.b 0, 0, 0, 14, 16, 16, 14, 0, 0
.dc.b 0, 20, 14, 16, 18, 18, 16, 14, 20
.dc.b 0, 18, 16, 18, 18, 18, 18, 16, 18
.dc.b 0, 18, 16, 18, 18, 18, 18, 16, 18
.dc.b 0, 20, 14, 16, 18, 18, 16, 14, 20
.dc.b 0, 0, 0, 14, 16, 16, 14, 0, 0
.dc.b 0,255, 0, 20, 18, 18, 20, 0,255
.else
.dc.b 0,255, 10, 10, 9, 9, 10, 10,255
.dc.b 0, 10, 0, 7, 8, 8, 7, 0, 10
.dc.b 0, 10, 7, 8, 9, 9, 8, 7, 10
.dc.b 0, 9, 8, 9, 0, 0, 9, 8, 9
.dc.b 0, 9, 8, 9, 0, 0, 9, 8, 9
.dc.b 0, 10, 7, 8, 9, 9, 8, 7, 10
.dc.b 0, 10, 0, 7, 8, 8, 7, 0, 10
.dc.b 0,255, 10, 10, 9, 9, 10, 10,255
.endif
.dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0,0
;確定石(自分の石があって相手がひっくり返せない)の得点
kakutei: .dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0
.if 0
.dc.b 0,255, 0, 18, 16, 16, 18, 0,255
.dc.b 0, 0, 0, 8, 8, 8, 8, 0, 0
.dc.b 0, 18, 8, 8, 10, 10, 8, 8, 18
.dc.b 0, 16, 8, 10, 10, 10, 10, 8, 16
.dc.b 0, 16, 8, 10, 10, 10, 10, 8, 16
.dc.b 0, 18, 8, 8, 10, 10, 8, 8, 18
.dc.b 0, 0, 0, 8, 8, 8, 8, 0, 0
.dc.b 0,255, 0, 18, 16, 16, 18, 0,255
.else
.dc.b 0,255, 0, 20, 15, 15, 20, 0,255
.dc.b 0, 0, 0, 1, 1, 1, 1, 0, 0
.dc.b 0, 20, 1, 1, 0, 0, 1, 1, 20
.dc.b 0, 15, 1, 0, 0, 0, 0, 1, 15
.dc.b 0, 15, 1, 0, 0, 0, 0, 1, 15
.dc.b 0, 20, 1, 1, 0, 0, 1, 1, 20
.dc.b 0, 0, 0, 1, 1, 1, 1, 0, 0
.dc.b 0,255, 0, 20, 15, 15, 20, 0,255
.endif
.dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0,0
;危険石(自分の石があって相手がひっくり返せる)の減点
kiken: .dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0
.if 0
.dc.b 0, 0, 29, 29, 19, 19, 29, 29, 0
.dc.b 0, 29,255, 9, 9, 9, 9,255, 29
.dc.b 0, 29, 9, 1, 1, 1, 1, 9, 29
.dc.b 0, 19, 9, 1, 1, 1, 1, 9, 19
.dc.b 0, 19, 9, 1, 1, 1, 1, 9, 19
.dc.b 0, 29, 9, 1, 1, 1, 1, 9, 29
.dc.b 0, 29,255, 9, 9, 9, 9,255, 29
.dc.b 0, 0, 29, 29, 19, 19, 29, 29, 0
.else
.dc.b 0, 0, 50, 15, 10, 10, 15, 50, 0
.dc.b 0, 50,255, 10, 10, 10, 10,255, 50
.dc.b 0, 15, 10, 1, 1, 1, 1, 10, 15
.dc.b 0, 10, 10, 1, 1, 1, 1, 10, 10
.dc.b 0, 10, 10, 1, 1, 1, 1, 10, 10
.dc.b 0, 15, 10, 1, 1, 1, 1, 10, 15
.dc.b 0, 50,255, 10, 10, 10, 10,255, 50
.dc.b 0, 0, 50, 15, 10, 10, 15, 50, 0
.endif
.dc.b 0, 0, 0, 0, 0, 0, 0, 0, 0,0
;----------------------------------------------------------------
;石を置ける位置のリストとレコード
.bss
.align 4
put_list_top:: .ds.l 65536 ;先読みの深さに応じて大きくする必要がある
put_record_btm::
;----------------------------------------------------------------
;疑似乱数列の初期化
.text
.align 4,$2048
mysrand::
move.l d0,-(sp)
DOS _GETDATE
move.l d0,-(sp)
DOS _GETTIME
add.l (sp)+,d0
move.l d0,random_work
move.l (sp)+,d0
rts
.data
.align 4
random_work:
.dc.l $FEDCBA98
;----------------------------------------------------------------
;疑似乱数の生成
;>d0.l:乱数
.text
.align 4,$2048
myrand::
move.l d1,-(sp)
move.l random_work,d0
move.l d0,d1
addq.l #1,d0
addq.l #4,d1
bsr imul
move.l d1,random_work
move.w d1,d0
swap.w d0
move.l (sp)+,d1
rts
;----------------------------------------------------------------
;32bit×32bit→64bit
;<d0.l:被乗数
;<d1.l:乗数
;>d0.l:結果(上位)
;>d1.l:結果(下位)
;?d0-d1
.text
.align 4,$2048
imul::
movem.l d2-d4,-(sp)
move.l d0,d3
move.l d1,d4
swap.w d3
swap.w d4
move.w d3,d2
mulu.w d1,d2
mulu.w d0,d1
mulu.w d4,d0
mulu.w d3,d4
add.l d2,d0
clr.w d3
addx.w d3,d3
swap.w d1
add.w d0,d1
swap.w d1
move.w d3,d0
swap.w d0
addx.l d4,d0
movem.l (sp)+,d2-d4
rts